package iot

import (
	"bytes"
	"charging_pile/util/protocol/jiuxing"
	"encoding/binary"
	"encoding/hex"

	"github.com/go-netty/go-netty"
	"github.com/go-netty/go-netty/codec"
	"github.com/go-netty/go-netty/utils"
	"github.com/zeromicro/go-zero/core/logx"
)

func JiuxingSubpackage() codec.Codec {
	return &subpackage{
		readBuff: make([]byte, 0),
	}
}

type subpackage struct {
	readBuff []byte
}

func (*subpackage) CodecName() string {
	return "jiuxingFrame"
}

func xr_check(bs []byte) byte {
	var res byte = 0
	for _, b := range bs {
		res = res ^ b
	}
	return res
}

func (d *subpackage) HandleRead(ctx netty.InboundContext, message netty.Message) {
	reader := utils.MustToBytes(message)
	d.readBuff = append(d.readBuff, reader...)
	for {
		if index := bytes.Index(d.readBuff, []byte{0x4A, 0x58}); index != -1 {
			d.readBuff = d.readBuff[index:]
		} else if len(d.readBuff) > 10240 {
			d.readBuff = make([]byte, 0)
			return
		}

		if len(d.readBuff) < 14 {
			return
		}

		packageLen := int(d.readBuff[13])*256 + int(d.readBuff[12]) + 15
		if len(d.readBuff) < packageLen {
			return
		}
		msg := d.readBuff[:packageLen]
		pl := binary.LittleEndian.Uint16(msg[12:14])

		logx.Info("jx msg up:", hex.EncodeToString(msg))
		check := xr_check(msg[2 : len(msg)-1])

		if check == msg[len(msg)-1] {
			pkg := jiuxing.Package{
				Cmd:        msg[2],
				Sn:         msg[3:11],
				Encryption: msg[11],
				PackageLen: pl,
				Payload:    msg[14 : 14+pl],
				Check:      msg[14+pl],
			}

			ctx.HandleRead(&pkg)
		} else {
			logx.Errorf("jx msg check error:%x %x", check, msg[len(msg)-1])
		}

		d.readBuff = d.readBuff[packageLen:]
	}
}

func (d *subpackage) HandleWrite(ctx netty.OutboundContext, message netty.Message) {
	msg := message.(jiuxing.Package)
	b := bytes.NewBuffer([]byte{})
	b.Write([]byte{0x4A, 0x58})
	b.WriteByte(msg.Cmd)
	b.Write(msg.Sn)
	b.WriteByte(msg.Encryption)
	b.WriteByte(byte(msg.PackageLen))
	b.WriteByte(byte(msg.PackageLen >> 8))
	b.Write(msg.Payload)

	msg.Check = xr_check(b.Bytes()[2 : len(b.Bytes())-1])

	b.WriteByte(msg.Check)
	logx.Info("jx msg down:", hex.EncodeToString(b.Bytes()))

	ctx.Write(b.Bytes())
}
